package com.shuqi.model.net;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import novel.proto.NovelBody;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;

import com.google.protobuf.InvalidProtocolBufferException;
import com.shuqi.common.utils.Log4an;
import com.shuqi.common.utils.Util;
import com.shuqi.interfaces.EventTypeConstants;
import com.shuqi.model.bean.BookChapterOssInfo;
import com.shuqi.model.net.listener.HttpRequestListener;
import com.shuqi.model.parse.HandlerBase;

/**
 * @des 描述 http请求接口
 */
public class HttpRequest implements Runnable {
    private HttpRequestBase httpRequest;
    private final int repeatNum = 3;
    /**
     * 请求的地址
     */
    private String[] mUrl = null;
    private String urlPtl = "http://";
    private List<BasicNameValuePair> mParams = null;

    private HttpClient httpClient = null;
    private HttpRequestListener mListener;
    private Context context;
    private HandlerBase dataParseAdapter;

    private boolean isAborted = false;
    // 请求地址
    private String requestUrl;
    private String mCdnUrl;
    private boolean isOss = false;

    public void setDataParseAdapter(HandlerBase dataParseAdapter) {
        this.dataParseAdapter = dataParseAdapter;
    }

    public void abort() {
        Log4an.e("RankListModel", "abort...之前：isAborted=" + isAborted);
        if (httpRequest != null && !httpRequest.isAborted()) {
            httpRequest.abort();
            isAborted = true;
        }
        Log4an.e("RankListModel", "abort...之后：isAborted=" + isAborted);
    }

    /**
     * 构造函数
     * 
     * @param context applicationContext
     * @param column
     * @param requestUrl
     * @param params 如果不为null则是post请求
     * @param listener
     */
    public HttpRequest(Context context, int column, String requestUrl,
            List<BasicNameValuePair> params, HttpRequestListener listener) {
        isAborted = false;
        this.context = context.getApplicationContext();
        this.mUrl = UrlManager.getUrls(context, column);
        this.requestUrl = requestUrl;
        this.mParams = params;
        this.mListener = listener;
        this.httpClient = CustomerHttpClient.getHttpClient();

        if (context == null || mListener == null || mUrl == null || TextUtils.isEmpty(requestUrl)) {
            throw new IllegalArgumentException("HttpRequest args is null");
        }

    }

    public HttpRequest(Context context, String cdnUrl, boolean isOss, HttpRequestListener listener) {
        isAborted = false;
        this.context = context.getApplicationContext();
        this.mCdnUrl = cdnUrl;
        this.mListener = listener;
        this.httpClient = CustomerHttpClient.getHttpClient();
        this.isOss = isOss;
        if (context == null || mListener == null || mCdnUrl == null) {
            throw new IllegalArgumentException("HttpRequest args is null");
        }
    }

    public void run() {

        try {
            int apn = HttpFactory.getApnType(context);
            if (apn == HttpFactory.NOT_EXIST) {
                // 无网络
                mListener.action(EventTypeConstants.EVENT_EXC_APNNOTEXIST, null);
            } else {
                if (mCdnUrl != null) {
                    doCdnGet(isOss);
                } else {
                    // 输出日志
                    if (mParams == null) {
                        doGet();
                    } else {
                        doPost();
                    }
                }
            }
        } finally {

        }
    }

    /**
     * @Des 描述 post请求方法
     */
    private void doPost() {
        InputStream stream = null;
        HttpResponse httpResponse = null;
        HttpEntity entity = null;
        int resp_code = 0;
        for (int i = 0; i < repeatNum; i++) {
            // 拼接串
            String curUrl = urlPtl + mUrl[i].concat(requestUrl);
            // log输出
            Log4an.v("zyc.HttpRequest", "url:" + curUrl);
            try {
                httpRequest =
                        HttpFactory.getHttpPostFromUrlStr(curUrl, context.getApplicationContext());
                ((HttpPost) httpRequest).setEntity(new UrlEncodedFormEntity(mParams, "UTF-8"));
                httpResponse = httpClient.execute(httpRequest);

                resp_code = httpResponse.getStatusLine().getStatusCode();
                Log4an.v("zyc.HttpRequest", "response code=" + resp_code);
                if (resp_code == HttpStatus.SC_OK) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (isAborted || i == 2) {// 最后一次重试
                    if (e instanceof ConnectionPoolTimeoutException
                            || e instanceof ConnectTimeoutException
                            || e instanceof SocketTimeoutException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_TIMEOUT, null);
                    } else if (e instanceof UnsupportedEncodingException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_4, null);
                    } else if (e instanceof MalformedURLException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_MALFORMEDURL, null);
                    } else if (e instanceof ClientProtocolException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_5, null);
                    } else if (e instanceof SocketException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_NETERR, null);
                    } else if (e instanceof IOException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_1, null);
                    } else {
                        mListener.action(EventTypeConstants.EVENT_EXC_REQUEST_OTHER, null);
                    }
                    if (httpRequest != null) {
                        httpRequest.abort();
                    }
                    return;
                }
            }
        }
        // 响应Code
        if (resp_code != HttpStatus.SC_OK) {
            if (httpRequest != null) {
                httpRequest.abort();
            }
            mListener.action(EventTypeConstants.EVENT_EXC_HTTPSTATUSERR, null);
            return;
        }
        try {
            entity = httpResponse.getEntity();
            if (entity.getContentEncoding() != null
                    && entity.getContentEncoding().getValue().contains("gzip")) {
                stream = new GZIPInputStream(entity.getContent());
                Log4an.d("lxs.XMLHelper:", "get isgzip:");
            } else {
                stream = entity.getContent(); // 110608
                Log4an.d("lxs.XMLHelper:", "get notgzip:");
            }
        } catch (IOException e) {
            e.printStackTrace();
            mListener.action(EventTypeConstants.EVENT_EXC_IO_2, null);
        }
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            reader.setContentHandler(dataParseAdapter);
            byte[] bytes = Util.getBytes(stream, 1024 * 2);// Utils.getBytes(stream,
            // 1024 * 2);
            // log输出
            try {
                ApplicationInfo info =
                        context.getPackageManager().getApplicationInfo(context.getPackageName(),
                                PackageManager.GET_META_DATA);

                if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                    Log4an.v("zyc.HttpRequest", new String(bytes));
                }
            } catch (Throwable e) {
                e.printStackTrace();
                Log4an.e("zyc.HttpRequest", "get xml err");
            }
            reader.parse(new InputSource(new InputStreamReader(new ByteArrayInputStream(bytes),
                    HTTP.UTF_8)));
            // 连接网络成功
            mListener.action(EventTypeConstants.EVENT_SUCCESS, dataParseAdapter.getParsedData());
        } catch (Throwable e) {
            e.printStackTrace();
            if (e instanceof IOException) {
                mListener.action(EventTypeConstants.EVENT_EXC_IO_3, null);
            } else if (e instanceof IllegalStateException) {
                mListener.action(EventTypeConstants.EVENT_EXC_ILLEGALSTATE, null);
            } else if (e instanceof FactoryConfigurationError) {
                mListener.action(EventTypeConstants.EVENT_EXC_FACTORYCONFIGURATION, null);
            } else if (e instanceof ParserConfigurationException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSERCONFIGURATION, null);
            } else if (e instanceof SAXException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER, null);
            } else {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER_OTHER, null);
            }

        } finally {
            if (stream != null)
                try {
                    stream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            if (httpRequest != null) {
                httpRequest.abort();
            }
        }
    }

    /**
     * @Des 描述 get请求方法
     */
    private void doGet() {
        InputStream stream = null;
        HttpResponse httpResponse = null;
        HttpEntity entity = null;
        int resp_code = 0;
        for (int i = 0; i < repeatNum; i++) {
            // 拼接串
            String curUrl = urlPtl + mUrl[i].concat(requestUrl);
            // log输出
            Log4an.v("zyc.HttpRequest", "url:" + curUrl);
            try {
                httpRequest =
                        HttpFactory.getHttpGetFromUrlStr(curUrl, context.getApplicationContext());
                httpResponse = httpClient.execute(httpRequest);
                
                resp_code = httpResponse.getStatusLine().getStatusCode();
                Log4an.v("zyc.HttpRequest", "response code=" + resp_code);
                if (resp_code == HttpStatus.SC_OK) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (isAborted || i == 2) {// 最后一次重试
                    if (e instanceof ConnectionPoolTimeoutException
                            || e instanceof ConnectTimeoutException
                            || e instanceof SocketTimeoutException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_TIMEOUT, null);
                    } else if (e instanceof UnsupportedEncodingException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_4, null);
                    } else if (e instanceof MalformedURLException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_MALFORMEDURL, null);
                    } else if (e instanceof ClientProtocolException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_5, null);
                    } else if (e instanceof SocketException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_NETERR, null);
                    } else if (e instanceof IOException) {
                        mListener.action(EventTypeConstants.EVENT_EXC_IO_1, null);
                    } else {
                        mListener.action(EventTypeConstants.EVENT_EXC_REQUEST_OTHER, null);
                    }
                    if (httpRequest != null) {
                        httpRequest.abort();
                    }
                    return;
                }
            }
        }
        // 响应Code
        if (resp_code != HttpStatus.SC_OK) {
            if (httpRequest != null) {
                httpRequest.abort();
            }
            mListener.action(EventTypeConstants.EVENT_EXC_HTTPSTATUSERR, null);
            return;
        }
        try {
            entity = httpResponse.getEntity();
            if (entity.getContentEncoding() != null
                    && entity.getContentEncoding().getValue().contains("gzip")) {
                stream = new GZIPInputStream(entity.getContent());
                Log4an.d("lxs.XMLHelper:", "get isgzip:");
            } else {
                stream = entity.getContent(); // 110608
                Log4an.d("lxs.XMLHelper:", "get notgzip:");
            }
        } catch (IOException e) {
            mListener.action(EventTypeConstants.EVENT_EXC_IO_2, null);
        }
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            reader.setContentHandler(dataParseAdapter);
            byte[] bytes = Util.getBytes(stream, 1024 * 2);// Utils.getBytes(stream,
            // 1024 * 2);
            // log输出
            try {
                ApplicationInfo info =
                        context.getPackageManager().getApplicationInfo(context.getPackageName(),
                                PackageManager.GET_META_DATA);

                if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                    Log4an.v("zyc.HttpRequest", new String(bytes));
                }
            } catch (Exception e) {
                Log4an.e("zyc.HttpRequest", "get xml err");
            }

            reader.parse(new InputSource(new InputStreamReader(new ByteArrayInputStream(bytes),
                    HTTP.UTF_8)));
            // 连接网络成功
            mListener.action(EventTypeConstants.EVENT_SUCCESS, dataParseAdapter.getParsedData());
        } catch (Throwable e) {
            e.printStackTrace();
            if (e instanceof IOException) {
                mListener.action(EventTypeConstants.EVENT_EXC_IO_3, null);
            } else if (e instanceof IllegalStateException) {
                mListener.action(EventTypeConstants.EVENT_EXC_ILLEGALSTATE, null);
            } else if (e instanceof FactoryConfigurationError) {
                mListener.action(EventTypeConstants.EVENT_EXC_FACTORYCONFIGURATION, null);
            } else if (e instanceof ParserConfigurationException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSERCONFIGURATION, null);
            } else if (e instanceof SAXException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER, null);
            } else {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER_OTHER, null);
            }

        } finally {
            if (stream != null)
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if (httpRequest != null) {
                httpRequest.abort();
            }
        }
    }

    /**
     * cdn地址get请求方式
     */
    private void doCdnGet(boolean isOss) {
        InputStream stream = null;
        HttpResponse httpResponse = null;
        HttpEntity entity = null;
        int resp_code = 0;
        try {
            httpRequest =
                    HttpFactory.getHttpGetFromUrlStr(mCdnUrl, context.getApplicationContext());
            httpResponse = httpClient.execute(httpRequest);

            resp_code = httpResponse.getStatusLine().getStatusCode();
            Log4an.v("zyc.HttpRequest", "response code=" + resp_code);
        } catch (Exception e) {
            e.printStackTrace();
            if (isAborted) {
                if (e instanceof ConnectionPoolTimeoutException
                        || e instanceof ConnectTimeoutException
                        || e instanceof SocketTimeoutException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_TIMEOUT, null);
                } else if (e instanceof UnsupportedEncodingException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_IO_4, null);
                } else if (e instanceof MalformedURLException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_MALFORMEDURL, null);
                } else if (e instanceof ClientProtocolException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_IO_5, null);
                } else if (e instanceof SocketException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_NETERR, null);
                } else if (e instanceof IOException) {
                    mListener.action(EventTypeConstants.EVENT_EXC_IO_1, null);
                } else {
                    mListener.action(EventTypeConstants.EVENT_EXC_REQUEST_OTHER, null);
                }
                if (httpRequest != null) {
                    httpRequest.abort();
                }
                return;
            }
        }
        // 响应Code
        if (resp_code != HttpStatus.SC_OK) {
            if (httpRequest != null) {
                httpRequest.abort();
            }
            mListener.action(EventTypeConstants.EVENT_EXC_HTTPSTATUSERR, null);
            return;
        }
        try {
            entity = httpResponse.getEntity();
            if (entity.getContentEncoding() != null
                    && entity.getContentEncoding().getValue().contains("gzip")) {
                stream = new GZIPInputStream(entity.getContent());
                Log4an.d("lxs.XMLHelper:", "get isgzip:");
            } else {
                stream = entity.getContent(); // 110608
                Log4an.d("lxs.XMLHelper:", "get notgzip:");
            }
            
        } catch (IOException e) {
            mListener.action(EventTypeConstants.EVENT_EXC_IO_2, null);
        }
        try {
            if (isOss) {
                byte[] bytes = Util.getBytes(stream, 1024 * 2);// Utils.getBytes(stream,
                // 1024 * 2);
                // log输出
                try {
                    ApplicationInfo info =
                            context.getPackageManager().getApplicationInfo(
                                    context.getPackageName(), PackageManager.GET_META_DATA);

                    if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                        Log4an.v("zyc.HttpRequest", new String(bytes));
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    Log4an.e("zyc.HttpRequest", "get xml err");
                }
                try {
                    
                    // old
                    // bufBase content = ProtobufParser.bufBase.parseFrom(new ByteArrayInputStream(bytes));
                    // BookChapterOssInfo base = BookChapterOssInfo.fromBufBase(content);
                    
                    // 修改文本加密处理
                    NovelBody.Body body = NovelBody.Body.parseFrom(new ByteArrayInputStream(bytes));
                    BookChapterOssInfo base = new BookChapterOssInfo();
                    int key = body.getKey();
                    byte[] tempContentBytes = body.getText().toByteArray();
                    if (key > 0) {
                        for (int i = 0; i < tempContentBytes.length; i++) {
                            tempContentBytes[i] = (byte) (tempContentBytes[i] ^ (key&0xFF));
                        }
                    }
                    base.setChapter_id(String.valueOf(body.getChapterId()));
                    base.setIs_manual(String.valueOf(body.getIsManual()));
                    base.setNovel_id(body.getNovelId().toStringUtf8());
                    base.setText(new String(tempContentBytes, "UTF-8"));
                    base.setTime_crawled(String.valueOf(body.getTimeCrawled()));
                    base.setUrl(body.getUrl().toStringUtf8());
                    
                    // 连接网络成功
                    mListener.action(EventTypeConstants.EVENT_SUCCESS, base);
                } catch (InvalidProtocolBufferException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                SAXParserFactory factory = SAXParserFactory.newInstance();
                SAXParser parser = factory.newSAXParser();
                XMLReader reader = parser.getXMLReader();
                reader.setContentHandler(dataParseAdapter);
                byte[] bytes = Util.getBytes(stream, 1024 * 2);// Utils.getBytes(stream,
                // 1024 * 2);
                // log输出
                try {
                    ApplicationInfo info =
                            context.getPackageManager().getApplicationInfo(
                                    context.getPackageName(), PackageManager.GET_META_DATA);

                    if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                        Log4an.v("zyc.HttpRequest", new String(bytes));
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    Log4an.e("zyc.HttpRequest", "get xml err");
                }
                
                reader.parse(new InputSource(new InputStreamReader(new ByteArrayInputStream(bytes),
                        HTTP.UTF_8)));
                // 连接网络成功
                mListener
                        .action(EventTypeConstants.EVENT_SUCCESS, dataParseAdapter.getParsedData());
            }
        } catch (Throwable e) {
            e.printStackTrace();
            if (e instanceof IOException) {
                mListener.action(EventTypeConstants.EVENT_EXC_IO_3, null);
            } else if (e instanceof IllegalStateException) {
                mListener.action(EventTypeConstants.EVENT_EXC_ILLEGALSTATE, null);
            } else if (e instanceof FactoryConfigurationError) {
                mListener.action(EventTypeConstants.EVENT_EXC_FACTORYCONFIGURATION, null);
            } else if (e instanceof ParserConfigurationException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSERCONFIGURATION, null);
            } else if (e instanceof SAXException) {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER, null);
            } else {
                mListener.action(EventTypeConstants.EVENT_EXC_PARSER_OTHER, null);
            }
        } finally {
            if (stream != null)
                try {
                    stream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            if (httpRequest != null) {
                httpRequest.abort();
            }
        }
    }

}
